# 自旋装饰器
import asyncio

from common.g.g import G_LOGGER, G_REDIS
from common.utils.lock.lock import release_lock, add_lock_self, add_lock


async def zip_func(origin_func, r_k):
    res = None
    try:
        res = await origin_func
    except Exception as e:
        G_LOGGER.exception(e)
    finally:
        await r_k
    return res


def lock(lock_key: str, lock_value: str, lock_time: int, execute_time: int):
    def wrapper(origin_func):
        async def inner(*args, **kwargs):
            ok = await G_REDIS.set(lock_key, lock_value, nx=True, px=lock_time)
            if ok:
                func1 = zip_func(origin_func(*args, **kwargs), release_lock(G_REDIS, lock_key, lock_value))
                func2 = add_lock_self(G_REDIS, lock_key, lock_value, lock_time, execute_time)
                res, _ = await asyncio.gather(func1, func2)
                return res
            else:
                ok = await add_lock(G_REDIS, lock_key, lock_value, lock_time, execute_time)
                if ok:
                    func1 = zip_func(origin_func(*args, **kwargs), release_lock(G_REDIS, lock_key, lock_value))
                    func2 = add_lock_self(G_REDIS, lock_key, lock_value, lock_time, execute_time)
                    res, _ = await asyncio.gather(func1, func2)
                    return res
                else:
                    return None
        return inner
    return wrapper

